﻿using OAZCSharpSdk.OAZ.Plugin.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace OAZCSharpSdk.OAZ.Plugin
{
    public class OAZPlugin
    {
        /// <summary>
        /// 插件初始化
        /// </summary>
        /// <param name="Name">插件名称(不能有特殊符号)</param>
        /// <param name="Version">插件版本</param>
        /// <param name="Author">插件作者</param>
        /// <param name="Description">插件描述</param>
        public OAZPlugin(string Name, string Version, string Author, string Description)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            this.Name = Name;
            this.Version = Version;
            this.Author = Author;
            this.Description = Description;
            Id = Guid.NewGuid().GetHashCode();
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            UnhandledException?.Invoke(sender, new PluginUnhandledExceptionEventArgs()
            {
                ExceptionObject = e.ExceptionObject,
                IsTerminating = e.IsTerminating
            });
        }

        /// <summary>
        /// 插件名称(不能有特殊符号)
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 插件版本
        /// </summary>
        public string Version { get; set; }
        /// <summary>
        /// 插件作者
        /// </summary>
        public string Author { get; set; }
        /// <summary>
        /// 插件描述
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// Skey(请勿修改)
        /// </summary>
        public string Skey { get { return "SDs6d8h7SD87HGA"; } }
        /// <summary>
        /// Sdk(请勿修改)
        /// </summary>
        public string Sdk { get { return "S2"; } }
        /// <summary>
        /// 插件ID(随机生成)
        /// </summary>
        public int Id { get; private set; }

        /// <summary>
        /// 收到QQ事件时
        /// </summary>
        public event EventHandler<PluginNotifyEventArgs> Notify;

        /// <summary>
        /// 有新好友时
        /// </summary>
        public event EventHandler<PluginNotifyEventArgs> Notify_Friend_New;

        /// <summary>
        /// 被好友删除时
        /// </summary>
        public event EventHandler<PluginNotifyEventArgs> Notify_Friend_Deleted;

        /// <summary>
        /// 有好友请求时
        /// </summary>
        public event EventHandler<PluginNotifyEventArgs> Notify_Friend_Request;

        /// <summary>
        /// 当对方同意了您的好友请求时
        /// </summary>
        public event EventHandler<PluginNotifyEventArgs> Notify_Friend_Request_Accpet;

        /// <summary>
        /// 当对方拒绝了您的好友请求时
        /// </summary>
        public event EventHandler<PluginNotifyEventArgs> Notify_Friend_Request_Refuse;

        /// <summary>
        /// 收到群消息时
        /// </summary>
        public event EventHandler<PluginGroupMessageEventArgs> GroupMessage;
        ///// <summary>
        ///// 私聊消息
        ///// </summary>
        //public event EventHandler<PrivateMessageEventArgs> PrivateMessage;
        /// <summary>
        /// 当插件被启用时
        /// </summary>
        public event EventHandler<PluginEnableArgs> Enable;
        /// <summary>
        /// 当插件被禁用时
        /// </summary>
        public event EventHandler<PluginDisableEventArgs> Disable;
        /// <summary>
        /// 当插件被载入完成时
        /// </summary>
        public event EventHandler<PluginLoadEventArgs> Load;
        /// <summary>
        /// 当用户按下“设置”时
        /// </summary>
        public event EventHandler<PluginEventArgs> Set;
        /// <summary>
        /// 当插件被卸载时
        /// </summary>
        public event EventHandler<PluginEventArgs> End;
        /// <summary>
        /// 发生未经捕获的异常时
        /// </summary>
        public event EventHandler<PluginUnhandledExceptionEventArgs> UnhandledException;


        #region Invoke

        #region Notify

        public void InvokeNotify(object sender, PluginNotifyEventArgs e)
        {
            Notify?.Invoke(sender, e);
        }

        public void InvokeNotifyFriendDeleted(object sender, PluginNotifyEventArgs e)
        {
            Notify_Friend_Deleted?.Invoke(sender, e);
        }

        public void InvokeNotifyFriendNew(object sender, PluginNotifyEventArgs e)
        {
            Notify_Friend_New?.Invoke(sender, e);
        }
        public void InvokeNotifyFriendRequest(object sender, PluginNotifyEventArgs e)
        {
            Notify_Friend_Request?.Invoke(sender, e);
        }

        public void InvokeNotifyFriendRequestAccpet(object sender, PluginNotifyEventArgs e)
        {
            Notify_Friend_Request_Accpet?.Invoke(sender, e);
        }

        public void InvokeNotifyFriendRequestRefuse(object sender, PluginNotifyEventArgs e)
        {
            Notify_Friend_Request_Refuse?.Invoke(sender, e);
        }

        #endregion

        public void InvokeEnd(object sender, PluginEndEventArgs e)
        {
            End?.Invoke(sender, e);
        }

        public void InvokeSet(object sender, PluginSetEventArgs e)
        {
            Set?.Invoke(sender, e);
        }

        public void InvokeEnable(object sender, PluginEnableArgs e)
        {
            Enable?.Invoke(sender, e);
        }

        public void InvokeGroupMessage(object sender,PluginGroupMessageEventArgs e)
        {
            GroupMessage?.Invoke(sender, e);
        }

        public void InvokeDisable(object sender, PluginDisableEventArgs e)
        {
            Disable?.Invoke(sender, e);
        }

        public void InvokeLoad(object sender, PluginLoadEventArgs e)
        {
            Load?.Invoke(sender, e);
        }
        #endregion

        /// <summary>
        /// 创建定时任务
        /// </summary>
        /// <param name="func">任务</param>
        /// <param name="delay">间隔(单位:毫秒)</param>
        /// <returns>任务ID</returns>
        public int SetInterval(Action func, int delay)
        {
            if (func == null)
            {
                return 0;
            }
            var timer = new Timer(_ => func.Invoke());
            int taskId = Guid.NewGuid().GetHashCode();
            timers.Add(taskId, timer);
            timer.Change(delay, delay);
            return taskId;
        }
        /// <summary>
        /// 创建延时任务
        /// </summary>
        /// <param name="func">任务</param>
        /// <param name="delay">间隔(单位:毫秒)</param>
        /// <returns>任务ID</returns>
        public int SetTimeout(Action func, int delay)
        {
            if (func == null)
            {
                return 0;
            }
            int taskId = Guid.NewGuid().GetHashCode();
            var timer = new Timer(_ =>
            {
                func.Invoke();
                ClearTimeout(taskId);
            });
            timers.Add(taskId, timer);
            timer.Change(delay, Timeout.Infinite);
            return taskId;
        }

        /// <summary>
        /// 清除定时任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns></returns>
        public int ClearInterval(int taskId)
        {
            if (timers.ContainsKey(taskId))
            {
                timers[taskId].Dispose();
                return 1;
            }
            return 0;
        }

        /// <summary>
        /// 取消所有任务
        /// </summary>
        public void ClearTasks()
        {
            foreach (var item in timers)
            {
                item.Value.Dispose();
            }
            timers.Clear();
        }

        /// <summary>
        /// 清除延时任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns></returns>
        public int ClearTimeout(int taskId) => ClearInterval(taskId);
        /// <summary>
        /// 唤醒调试器进行调试
        /// </summary>
        public void Debug() => Debugger.Launch();
        /// <summary>
        /// 任务列表
        /// </summary>
        private Dictionary<int, System.Threading.Timer> timers = new Dictionary<int, System.Threading.Timer>();
    }
}
